#include <malloc.h>
#include<stdio.h>
#include<stdlib.h>

/**** petite macro pour choisir le type des matrices et vecteurs (entiers, reels) ******/
// gcc -DTYPE_INT
#ifdef TYPE_INT
typedef int T;
#else
#ifdef TYPE_FLOAT
typedef float T;
#else
 #error "Need to give MACRO definition for element type : -DTYPE_INT or -DTYPE_FLOAT"
#endif
#endif
/***************************************************************************************/


#include "fonctions.c"



/*********** programme principal********************************/ 

int main(int argc, char *argv[])
{


	//declarations parametres
	// on precisera la taille des matrices en ligne de commande
	int dim1=atoi(argv[1]);
	int dim2=atoi(argv[2]);
	int i,j;
	int Nmax=dim1-1;
	T **A;
	T* u;
	T* v;
 
	//pour le stockage COO des matrices creuses
	int **I; //tableau d'indices
	T* Values; //tableau de valeurs non nuls de la matrice
 
	//pour le stockage CSR des matrices creuses
	int *IA; //stocke le nombre d'elements non nuls par ligne
	int *J; //stocke les numéros de colonnes des elements non nuls
 
	//pour le stockage MEI des matrices creuses
	T **AA; //stocke les valeurs des coefficients non nuls par ligne
	int **JA; //contient les numéros de colonne des elements non nuls
	
	//pour le stockage BND de matrices creuses
	T **Bande; //stocke les valeurs des coefficients non nuls par bande
	int nbBandeSup=0;
	int nbBandeInf=0;
	int n=nbBandeSup+nbBandeInf+1;
 
	//Allocation dynamique Matrice Indice et vecteur Value equivalent a la matrice unite
	I =(int**) malloc(dim1*sizeof(*I));
	Values=malloc(dim1*sizeof(T));
	for(i=0;i<dim1;i++)
	{
		I[i]=(int*)malloc(2*sizeof(**I));
		Values[i]=(T)1;
		I[i][0]=i;
		I[i][1]=i;
	} 
	//Allocation dynamique vecteur IA et J equivalent a la matrice unite
	IA=malloc((dim1+1)*sizeof(int));
	J=malloc(dim1*sizeof(int));
	IA[dim1]=1;
	for(i=0;i<dim1;i++)
	{
		IA[i]=1;
		J[i]=i; 
	}   
	//allocation dynamique matrice AA et JA eqivalent a la matrice unite 
	AA=(T**)malloc(dim1*sizeof(*AA));
	JA=(int**)malloc(dim1*sizeof(*JA));
	for(i=0;i<dim1;i++)
	{
		AA[i]=(T*)malloc((dim1-1)*sizeof(**AA));
		JA[i]=(int*)malloc((dim1-1)*sizeof(**JA));
		AA[i][0]=1;
		JA[i][0]=i;
	}
	for(i=0;i<dim1;i++)
	{
		for(j=0;j<dim1-1;j++)
		{
			AA[i][j]=0;
			JA[i][j]=i; 
		}
	} 
	
	//allocation dynamique matrice Bande eqivalent a la matrice unite 
	Bande=(T**)malloc(dim1*sizeof(*Bande));
	for(i=0;i<dim1;i++)
	{
		Bande[i]=(T*)malloc(n*sizeof(**Bande));
   }
   for(i=0;i<dim1;i++)
   {
	   Bande[i][nbBandeInf]=1;
   }
		
 
	//pour le stockage de matrice dense
	//allocation dynamique en memoire de A, u et du vecteur resultat, prenons A=Identite
	A =(T**) malloc(dim1*sizeof(*A));
	u=malloc(dim2*sizeof(T));
	v=malloc(dim1*sizeof(T));
	for(i=0;i<dim1;i++)
	{
		A[i]=(T*)malloc(dim2*sizeof(**A));
		for(j=0;j<dim2;j++)
		{
			A[i][j]=(T)0;
			u[j]=(T)j;
		}
		A[i][i]=(T)1;
	}
 
	////------------------------Affichage matrice

	////affichons la matrice I et le tableau de valeurs
	//for (i=0;i<dim1;i++)
	//{
		//for (j=0;j<2;j++)
		//{
			//printf("%d\t", I[i][j]);
		//}
		//printf("|%f\n",Value[i] );
	//}

	//printf("\n");
  
	////affichons la matrice A
	//for (i=0;i<dim1;i++)
	//{
		//for (j=0;j<dim2;j++)
		//{
			//printf("%f\t", A[i][j]);
		//}
		//printf("|%f\n",u[i] );
	//}

	//printf("\n" );


	//appel fonctions produit

	GEMV(A,u,v,dim1,dim2,argv[3]);
	//for(i=0;i<dim1;i++)
	//  {printf("Avec GEMV v[%d]=%f\n",i,resultat[i]);} //on affiche le vecteur resultat
	//printf("on passe a creuse_classique\n");
	//printf("\n");
	SPMV_COO(I,Values,u,v,dim2);
	//for(i=0;i<dim1;i++)
	//  {printf("Avec SPMV v[%d]=%f\n",i,resultat[i]);} //on affiche le vecteur resultat
	SPMV_CSR(IA,J,Values,u,v,dim1);
	SPMV_EI(AA,JA,u,v,dim1,Nmax);
	SPMV_BND(Bande,u,v,dim1,nbBandeInf,nbBandeSup);

	/**************liberation memoire***********************************************/
	//liberation en memoire de A,u et v
	for(i=0;i<dim1;i++)
	{
		free(A[i]);
		free(I[i]);
		Bande[i];
	}
	free(A);
	free(I);
	free(Bande);
	free(u);
	free(v);
	free(J);
	
	//liberation en memoire de AA et JA 
	for(i=0;i<dim1-1;i++)
	{
		free(AA[i]);
		free(JA[i]);
	}
	free(AA);
	free(JA);
/****************************************************************************/

return 0;
}
